/* TODO:
    
    X upload form resize bug
    X disable prev/next as appropriate
    X edit title of album
        - set dataset picture from album?
    X delete photo
    X prepend picture on upload?
        X means basically need to delete all pictures and re-render?
    X edit photo details
    X date format
    X paging on home view
    N performance
        N is the resize function being called too often?
        N too many images on one page?

    X escape html in user input
    X better error handling
    X better loading handling
    N poll on home for updates
    N poll on detail for comment updates
    N background resize task
    X metadata in seperate keys to allow finer control of who can post?
        X you can't use a json structure concurrently..
    X comments
        N num comments on home view
        X add comment
        X render comments on details page
        X delete comment if owner
        X comments in separate key so that others can write
    X only owner sees edit controls

    X group awareness
        X extra field in peerscape.contentInfo for type (?)
        X is_group_aware flag in application info?
    
    X better control over who can write
        N allow friends to add photos?
        X allow group members to add photos 
            X pos with role e.g. 'admin'

    X hide comments altogether setting?



 --------
    X back button?
    - slideshow
    - preferences
        - who can leave comments?

    - is each instance of app an 'album'?
        - or does app need to support sub-ablums?

    X feeds to push content up to profile?
        X atom?
    - upload post redirects to some other (get) page?

*/
var peerscape = null;
var app = function() {
    return {
        UUID_RE: /UUID/g,
        METADATA_PATH: '/content/photos/metadata.json',
        PHOTO_ENTRY_PATH_A: '/content/photos/entries/',
        PHOTO_ENTRY_PATH_B: '/entry.json',
        COMMENTS_PATH_A: '/content/photos/comments/',
        COMMENTS_PATH_B: '/comments.json',
        JSON_FEED_PATH: '/content/feeds/atom.json',
        PREFS_PATH: '/content/prefs/prefs.json',
        prefs: null,
        metadata: null,
        entries: null,
        entriesCache: null,
        _debug: true,
        _loaded: false,
        _setup: function() {
            if (app.util.isAdmin(peerscape.contentInfo)) {
                // make sure the data is there. only really needed first time.
                var metadata = {
                    title: peerscape.contentInfo.title,
                    created: app.util.getTimestamp(),
                    updated: app.util.getTimestamp(),
                    author: {
                        name: peerscape.contentInfo.owner.name,
                        id: peerscape.contentInfo.owner.iid,
                    },
                    id: peerscape.contentInfo.iid,
                    generator: {
                        uri: peerscape.contentInfo.application.iid,
                        name: peerscape.contentInfo.application.name
                    },
                };
                $.post('/postif'+app.METADATA_PATH, {value: $.toJSON(metadata)});

                // make sure we have a prefs data structure
                var prefs = {
                    auto_refresh: true,
                    enable_comments: true,
                    group_write_roles: ['admin']
                };
                $.post('/postif'+app.PREFS_PATH, {value: $.toJSON(prefs)});
                
                // make sure at least empty feeds exist
                $.post('/postif'+app.JSON_FEED_PATH, {value: $.toJSON(app.util.generateJSONFeed(metadata))});
            }
        },
        screens: {},
        curScreen: null,
        init: function() {
            app.util._get_peerscape();

            // init the error dialog
            app.error.init();

            // show loading anim
            app.loading.init();
            app.loading.show();

            // call _setup
            app._setup();

            // fetch the preferences
            app.fetchPrefs(
                function(data) {
                    app.prefs = eval('(' + data + ')');
                    
                    if (app.util.isGroup(peerscape.contentInfo)) {
                        // grant permissions for group admins to upload photos
                        $.post('/grant/index', { who: peerscape.contentInfo.parent_profile.iid, pattern: '/content/photos/...', roles: $.toJSON(app.prefs.group_write_roles)});

                        // grant permissions for group members to write comments
                        $.post('/grant/index', { who: peerscape.contentInfo.parent_profile.iid, pattern: '/content/photos/comments/*/!/comments.json'});
                    }
                    else {
                        // grant permissions for friends to write comments
                        $.post('/grant/index', { who: peerscape.contentInfo.owner.iid, pattern: '/content/photos/comments/*/!/comments.json'});
                    }
                },
                function (xhr, textStatus, errorThrown) {
                    // ignore
                });

            // init the main view
            app.home.init();

            // init the settings view
            app.settings.init();

            // init the upload form
            app.upload.init();
            
            // init the detail view
            app.detail.init();

            if (app.util.isAdmin(peerscape.contentInfo)) {
                $('#tabNav #homeTab a').eq(0)
                    .bind('click', function() {
                        app.util.log('load 0');
                        app.load('home');
                        return false;
                    })
                    .show();
                $('#tabNav #uploadTab a').eq(0)
                    .bind('click', function() {
                        app.util.log('load 1');
                        app.load('upload');
                        return false;
                    })
                    .show();
                $('#tabNav #settingsTab a')
                    .bind('click', function() {
                        app.util.log('load 2');
                        app.load('settings');
                        return false;
                    })
                    .show();

                $('#tabNav').show();
            }
            else {
                $('#tabNav #homeTab a').hide();
                $('#tabNav #uploadTab a').hide();
                $('#tabNav #settingsTab a').hide();
            }
        },
        postInit: function() {
            $.historyInit(app.historyHandler);
            //$.history.init(app.historyHandler);
            //app.historyHandler('home');
            app._loaded = true;
        },
        load: function(hash) {
            app.util.log('load: [' + hash + ']');
            $.historyLoad(hash);
            //$.history.load(hash);
            //app.historyHandler(hash);
        },
        historyHandler: function(hash) {
            if (hash && hash == 'noop') {
                return false;
            }

            /* this is some kind of bug in safari */
            if ($.browser.safari) {
                if (hash == '' && app._loaded) {
                    return false;
                }
                if (hash == '' && !app._loaded) {
                    app.load('home');
                    return false;
                }
            }

            if (app.curScreen != hash) {
                if (!hash || hash.indexOf('home') == 0) {
                    var page = ((hash && hash.indexOf(':') != -1) ? hash.split(':') : 1);
                    if (!page || page == undefined) {
                        page = 1;
                    }
                    else if (page != 1) {
                        page = page[1];
                    }

                    app.home.curPage = page;
                    app.home.refresh(true);
                    app.home.show();
                    peerscape.common.scrollToTop();
                }
                else if (hash == 'upload') {
                    app.upload.show();
                    peerscape.common.scrollToTop();
                }
                else if (hash == 'settings') {
                    app.settings.show();
                    peerscape.common.scrollToTop();
                }
                else {
                    app.detail.show(hash);
                    peerscape.common.scrollToTop();
                }
                app.curScreen = hash;
            }
        },
        hideAll: function() {
            app.home.poll.stop();
            for (var s in app.screens) {
                app.screens[s].hide();
            }
        },
        error: {
            init: function() {
                $('#error .ok a').eq(0)
                    .bind('click', function() {
                        app.error.clear();
                        app.loading.hide();
                        return false;
                    });
            },
            set: function(msg) {
                $('#error').show().find('p.message').html(msg);
            },
            clear: function() {
                $('#error').hide().find('p.message').html('');
            }
        },
        getPhotoEntriesPath: function() {
            return app.PHOTO_ENTRY_PATH_A;
        },
        getSinglePhotoEntryPath: function(id) {
            return app.PHOTO_ENTRY_PATH_A + id + app.PHOTO_ENTRY_PATH_B;
        },
        getCommentsPath: function(id) {
            return app.COMMENTS_PATH_A + id;
        },
        getUserCommentsPath: function(id, iid) {
            if (iid) {
                return app.COMMENTS_PATH_A + id + '/' + iid + app.COMMENTS_PATH_B;
            }
            return app.COMMENTS_PATH_A + id + '/!' + app.COMMENTS_PATH_B;
        },
        fetchPrefs: function(successF, errorF) {
            $.ajax({
                type: 'GET',
                url: '/get'+app.PREFS_PATH,
                async: false,
                success: successF,
                error: errorF
            });
        },
        fetchEntries: function(successF, errorF) {
            $.ajax({
                type: 'GET',
                url: '/getall'+app.getPhotoEntriesPath(),
                success: successF,
                error: errorF
            });
        },
        fetchMetadata: function(successF, errorF) {
            $.ajax({
                type: 'GET',
                url: '/get'+app.METADATA_PATH,
                success: successF,
                error: errorF
            });
        },
        _processEntriesData: function(data) {
            // sort by date
            var ret = data.sort(function(a, b) {
                return (a.created < b.created);
            });

            if (!app.entriesCache) {
                app.entriesCache = {};
            }

            return ret;
        },
        /* -------------- HOME ---------------- */
        home: {
            ITEM_TEMPLATE: null,
            PAGER_ITEM_TEMPLATE: null,
            PHOTOS_PER_PAGE: 10,
            curPage: 1,
            numPages: 1,
            lastMark: 0,
            init: function() {
                // get the photo thumbnail template
                app.home.ITEM_TEMPLATE = $('#homeScreen #homeTemplate').clone();
                app.home.ITEM_TEMPLATE.removeAttr('id');
                app.home.ITEM_TEMPLATE.removeAttr('class');

                // get the pager item template
                app.home.PAGER_ITEM_TEMPLATE = $('#homeScreen #photoPager .template').clone();
                app.home.PAGER_ITEM_TEMPLATE.removeAttr('class');

                // make sure template doesn't get used. (maybe remove altogether?)
                $('#homeScreen #homeTemplate').find('.available').removeAttr('class');

                // set the title
                app.home.setTitle(peerscape.contentInfo.title);
                app.screens['homeScreen'] = $('#homeScreen');
            },
            setTitle: function(t) {
                $('#mainTitle').html(t);
            },
            refresh: function(bHard) {
                app.home.poll.stop();

                app.loading.show();
                if (bHard) {
                    // fetch the photos
                    app.fetchMetadata(
                        function(data) {
                            app.metadata = eval('(' + data + ')');
                        },
                        function (xhr, textStatus, errorThrown) {
                            // ignore 
                        }
                    );
                    app.fetchEntries(
                        function(data) {
                            app.entries = app._processEntriesData(eval('(' + data + ')'));
                            app.home.render();
                            app.loading.hide();
                            ++app.home.lastMark;
                        },
                        function (xhr, textStatus, errorThrown) {
                            if (xhr.status == 404) {
                                app.error.set('Photo information not found.');
                            }
                            else {
                                app.error.set('');
                            }
                        }
                    );
                }
                else {
                    app.home.render();
                    app.loading.hide();
                }
            },
            removeAll: function() {
                $('#photos').empty();
            },
            render: function() {
                if (app.entries.length > 0) {
                    $('#homeScreen .inner #none').hide();

                    app.home.removeAll();

                    var starti = (app.home.curPage - 1) * app.home.PHOTOS_PER_PAGE;
                    var endi = starti + app.home.PHOTOS_PER_PAGE;
                    if (endi > app.entries.length) {
                        endi = app.entries.length;
                    }
                    app.util.log('home.r: '+ app.home.curPage + ' ('+starti+','+endi+')');
                    for (var e=starti; e<endi; e++) {
                        if (app.entries[e]) {
                            if ($('#photos').find('#'+app.entries[e].id).length > 0) {
                                // already exists, skip
                                continue;
                            }
                            if ($('#photos tr').length > 0 && $('.available').length > 0) {
                                app.home._renderItem($('.available').eq(0), app.entries[e]);
                            }
                            else {
                                var row = app.home.ITEM_TEMPLATE.clone();
                                app.home._renderItem(row.find('.available').eq(0), app.entries[e]);

                                // add item to list
                                $('#homeScreen #photos').append(row);

                                // add to cache
                                app.entriesCache[app.entries[e].id] = app.entries[e].id;
                            }
                        }
                    }

                    // show the photos
                    $('#photos').show();

                    peerscape.common.resize();
                }
                else {
                    if (app.util.isAdmin(peerscape.contentInfo)) {
                        $('#homeScreen .inner #none .admin').show();
                    }
                    else {
                        $('#homeScreen .inner #none .admin').hide();
                    }
                    $('#homeScreen .inner #none').show();

                    // hide the photos
                    $('#photos').hide();
                    
                }
                app.home.renderPager();

                if (app.prefs && app.prefs.auto_refresh) {
                    app.home.poll.start();
                }
            },
            _renderItem: function(item, entry) {
                //app.util.log('render home id:', entry.id);
                item.attr('id', entry.id);
                item.attr('class', 'used');

                // populate image with current photo url
                item.find('.photo a').html('<img src="/get/application/images/loading.gif" class="loading"/>');
                app.util.imageLoader(entry.id, entry.content.src, item.find('.photo a img'));

                // add a handler to show photo detail
                item.find('.photo a').eq(0)
                    .attr('href', '#'+entry.id)
                    .unbind('click')
                    .bind('click', function() {
                        app.util.log('load 3');
                        app.load(entry.id);
                        return false;
                    });

                item.find('.metadata h3 a').eq(0)
                    .html(entry.title)
                    .attr('href', '#'+entry.id)
                    .unbind('click')
                    .bind('click', function() {
                        app.util.log('load 4');
                        app.load(entry.id);
                        return false;
                    });

                item.find('.metadata p.updated').eq(0)
                    .html(app.util.formatTimestamp(entry.updated, true));

            },
            renderPager: function() {
                if (!app.entries || app.entries.length == 0) {
                    $('#homeScreen #photoPager').hide();
                    return;
                }
                
                app.home.numPages = Math.ceil(app.entries.length / app.home.PHOTOS_PER_PAGE);
                app.util.log('['+app.entries.length + '][' + app.home.PHOTOS_PER_PAGE + '][' + app.home.numPages + ']');
                $('#homeScreen #photoPager p span').html(app.home.curPage + '/' + app.home.numPages);

                // insert pages
                $('#homeScreen #photoPager ul').empty();
                for (var p=1; p<=app.home.numPages; p++) {
                    var item = app.home.PAGER_ITEM_TEMPLATE.clone();
                    app.home._renderPagerItem(item, p);
                    $('#homeScreen #photoPager ul').append(item);
                }

                $('#homeScreen #photoPager').show();
            },
            _renderPagerItem: function(item, p) {
                item.find('a').eq(0)
                    .attr('href', '#home:' + p)
                    .html(p)
                    .bind('click', function() {
                        app.util.log('will load: home:'+p);
                        app.load('home:' + p);
                        return false;
                    });

                // select current page link
                if (p == app.home.curPage) {
                    item.find('a').attr('class', 'selected');
                }
            },
            poll: {
                DELAY_MS: 30000,
                id: null,
                start: function() {
                    app.home.poll.id = setTimeout(app.home.poll.tick, app.home.poll.DELAY_MS);
                },
                stop: function() {
                    clearTimeout(app.home.poll.id);
                },
                tick: function() {
                    app.home.refresh(true);
                }
            },
            hide: function() {
                app.home.poll.stop();
                $('#homeScreen').hide();
            },
            show: function() {
                app.hideAll();
                $('#homeScreen').show();
                app.util.selectTabNav('homeTab');
                peerscape.common.resize();
            }
        },
        /* -------------- DETAIL ---------------- */
        detail: {
            COMMENT_TEMPLATE: null,
            curItem: null,
            init: function() {
                app.detail.COMMENT_TEMPLATE = $('#detailScreen #commentTemplate').clone();
                app.detail.COMMENT_TEMPLATE.removeAttr('id');
                app.detail.COMMENT_TEMPLATE.removeAttr('class');

                if (app.util.isAdmin(peerscape.contentInfo)) {
                    $('#detailScreen #editNav a.edit')
                        .bind('click', function() {
                            app.detail.edit.editFormCur();
                            return false;
                        })
                        .show();

                    $('#detailScreen #editNav a.delete')
                        .bind('click', function() {
                            if (confirm('Are you sure you want to delete this photo?')) {
                                app.detail.deleteCur();
                            }
                            return false;
                        })
                        .show();
                }
                else {
                    $('#detailScreen #editNav a.edit').hide();
                    $('#detailScreen #editNav a.delete').hide();
                }

                $('#detailScreen #editForm').submit(function() { return false; });
                $('#detailScreen #editForm input.submit')
                    .bind('click', function() {
                        app.detail.edit.save();
                        app.home.refresh();
                        return false;
                    });
                $('#detailScreen #editForm input.cancel')
                    .bind('click', function() {
                        app.detail.edit.cancel();
                        return false;
                    });

                $('#detailScreen #commentForm').submit(function() { return false; });
                $('#detailScreen #commentForm input.submit')
                    .bind('click', function() {
                        app.detail.comments.save();
                        return false;
                    });
                
                // register this screen
                app.screens['detailScreen'] = $('#detailScreen');
            },
            getCurId: function() {
                if (app.metadata && app.detail.curItem) {
                    return app.entries[app.detail.curItem].id;
                }
                return null;
            },
            deleteCur: function() {
                app.loading.show();
                var photoId = app.detail.getCurId();

                // delete comments. note that the post needs a body otherwise http server can timeout
                $.ajax({
                    type: 'POST',
                    url: '/deleteall'+app.getCommentsPath(photoId),
                    data: { value: 'something to put in post body' },
                    async: false
                });
                app.detail.comments.commentsList = null;

                // delete the photo metadata entry
                $.ajax({
                    type: 'POST',
                    url: '/delete'+app.getSinglePhotoEntryPath(photoId),
                    data: { value: 'something to put in post body' },
                    async: false
                });

                if (app.detail.curItem == 0) {
                    app.entries = [];
                }
                else {
                    app.entries.splice(app.detail.curItem, 1);
                }

                // delete the photo
                $.ajax({
                    type: 'POST',
                    url: '/delete/content/photos/'+photoId,
                    data: { value: 'something to put in post body' },
                    async: false
                });

                // update the album metadata
                if (app.metadata) {
                    app.metadata.updated = app.util.getTimestamp();
                    $.post('/post'+app.METADATA_PATH, {value: $.toJSON(app.metadata)});
                }

                // update the album feeds
                $.post('/post'+app.JSON_FEED_PATH, {value: $.toJSON(app.util.generateJSONFeed())});

                app.detail.curItem = null;
                app.loading.hide();
                app.util.log('load 5');
                app.load('home');
            },
            render: function(id) {
                app.loading.show();
                if (!app.metadata || !app.entries) {
                    app.fetchMetadata(
                        function(data) {
                            app.metadata = eval('(' + data + ')');
                        },
                        function() {}
                    );
                    app.fetchEntries(
                        function(data) {
                            app.entries = app._processEntriesData(eval('(' + data + ')'));
                            app.detail.show(id);
                        },
                        function() {}
                    );
                    return false;
                }

                var entry = null;
                for (var e in app.entries) {
                    if (app.entries[e].id == id) {
                        entry = app.entries[e];
                        app.detail.curItem = e;
                        break;
                    }
                }
                if (!entry) {
                    app.loading.hide();
                    app.error.set('No such photo: ' + id);
                    app.detail.hide();
                    app.util.log('load 6');
                    app.load('home');
                    return false;
                }

                app.detail._renderItem(app.entries[e]);
                app.loading.hide();
                return true;
            },
            _renderItem: function(entry) {
                var pId = app.detail.getPrevId();
                $('#detailScreen #photoNav a.prev').eq(0)
                    .attr('href', '#' + pId)
                    .unbind('click')
                    .bind('click', function() {
                        if (pId != 'noop') {
                            app.util.log('load 7');
                            app.load(pId);
                        }
                        return false;
                    });
                app.detail.enablePrev(app.detail.curItem != 0);

                nId = app.detail.getNextId();
                $('#detailScreen #photoNav a.next').eq(0)
                    .attr('href', '#' + nId)
                    .unbind('click')
                    .bind('click', function() {
                        if (nId != 'noop') {
                            app.util.log('load 8');
                            app.load(nId);
                        }
                        return false;
                    });
                app.detail.enableNext(app.detail.curItem < app.entries.length-1);

                $('#detailScreen #close').eq(0)
                    .unbind('click')
                    .bind('click', function() {
                        app.util.log('load 9');
                        app.load('home:'+app.home.curPage);
                        return false;
                    });

                var item = $('#detailScreen').eq(0);
                item.find('.photo').html('<img src="/get/application/images/loading.gif"/>');
                app.util.imageLoader(entry.id, entry.content.src, item.find('.photo img'));

                item.find('h3').eq(0)
                    .html(entry.title);

                item.find('p.updated').eq(0)
                    .html(app.util.formatTimestamp(entry.updated));

                item.find('p.author').eq(0)
                    .html('Uploaded by: <a href="http://'+entry.author.iid+'.hexlabel.net/" target="_top">'+entry.author.name+'</a>');

                if (entry.summary) {
                    item.find('p.description').eq(0)
                        .html(entry.summary);
                }
                else {
                    item.find('p.description').html('');
                }

                $('#editFormWrapper').hide();
                $('#infoWrapper').show();

                // extra tools
                $('#detailScreen #extraTools .directLink').eq(0)
                    .attr('href', entry.content.src);

                $('#detailScreen #extraTools #setPictureStatus').html('');

                if (app.util.isAdmin(peerscape.contentInfo)) {
                    $('#detailScreen #extraTools .setPicture').eq(0)
                        .before(' | ')
                        .unbind('click')
                        .bind('click', function() {
                            app.detail.setCurAsMainPicture(entry.content.src);
                            return false;
                        });
                 }
                 else {
                    $('#detailScreen #extraTools .setPicture').hide();
                 }

                app.detail.comments.init(app.detail.getCurId());

            },
            setCurAsMainPicture: function(src) {
                // set the picture
                $.ajax({
                    type: 'POST',
                    url: '/content/picture',
                    data: { ref: src },
                    success: function(data) {
                        $('#detailScreen #extraTools #setPictureStatus')
                            .attr('class', 'ok')
                            .html('OK');
                    },
                    error: function (xhr, textStatus, errorThrown) {
                        $('#detailScreen #extraTools #setPictureStatus')
                            .attr('class', 'error')
                            .html('FAILED');
                    }
                });
            },
            enablePrev: function(bOn) {
                if (bOn) {
                    $('#detailScreen #photoNav a.prev').eq(0)
                        .attr('class', 'prev');
                }
                else {
                    $('#detailScreen #photoNav a.prev').eq(0)
                        .attr('class', 'prev disabled');
                }
            },
            getPrevId: function() {
                if (app.detail.curItem == null) {
                    return 'noop';
                }
                if (app.detail.curItem == 0) {
                    return 'noop';
                }
                return app.entries[app.detail.curItem-1].id;
            },
            enableNext: function(bOn) {
                if (bOn) {
                    $('#detailScreen #photoNav a.next').eq(0)
                        .attr('class', 'next');
                }
                else {
                    $('#detailScreen #photoNav a.next').eq(0)
                        .attr('class', 'next disabled');
                }
            },
            getNextId: function() {
                if (app.detail.curItem == null) {
                    return 'noop';
                }
                if (app.detail.curItem == (app.entries.length-1)) {
                    return 'noop';
                }
                return app.entries[parseInt(app.detail.curItem)+1].id;
            },
            hide: function() {
                $('#detailScreen').hide();
            },
            show: function(id) {
                app.hideAll();
                if (app.detail.render(id)) {
                    $('#detailScreen').show();
                }
                else {
                    app.detail.hide();
                }
                app.util.selectTabNav('homeTab');
                peerscape.common.resize();
            },

            /* -------------- DETAIL: EDIT ---------------- */
            edit: {
                /* initilaize edit form for the current entry */
                editFormCur: function() {
                    $('#editForm #editTitle').val(peerscape.common.unescapeHTML(app.entries[app.detail.curItem].title));
                    $('#editForm #editDescription').val(peerscape.common.unescapeHTML(app.entries[app.detail.curItem].summary));
                    $('#infoWrapper').hide();
                    $('#editFormWrapper').slideDown('fast', peerscape.common.resize);
                },
                onsubmit: function() {
                    /* validate the form */
                    if (app.util.isEmpty($('#editForm #editTitle').val())) {
                        alert('Please enter a title');
                        return false;
                    }
                    return true;
                },
                save: function() {
                    if (!app.detail.edit.onsubmit()) {
                        return false;
                    }
                    app.loading.show();
                    var entry = app.entries[app.detail.curItem];
                    entry.title = peerscape.common.escapeHTML($('#editForm #editTitle').val());
                    entry.summary = peerscape.common.escapeHTML($('#editForm #editDescription').val());
                    entry.updated = app.util.getTimestamp();
                    $.post('/post'+app.getSinglePhotoEntryPath(entry.id), {
                        value: $.toJSON(entry)
                    });
                    app.entries[app.detail.curItem] = entry;
                    app.detail._renderItem(entry);

                    // update the metadata
                    app.metadata.updated = app.util.getTimestamp();
                    $.post('/post'+app.METADATA_PATH, {value: $.toJSON(app.metadata)});

                    // update the feeds
                    $.post('/post'+app.JSON_FEED_PATH, {value: $.toJSON(app.util.generateJSONFeed())});

                    $('#editFormWrapper').hide();
                    $('#infoWrapper').show();
                    app.loading.hide();
                    return false;
                },
                cancel: function() {
                    $('#editFormWrapper').slideUp('fast');
                    $('#infoWrapper').show();
                    peerscape.common.resize();
                    return false;
                }
            },
            /* -------------- DETAIL: COMMENTS ---------------- */
            comments: {
                commentsList: null,
                init: function(id) {
                    if (app.prefs && app.prefs.enable_comments) {
                        app.loading.show();

                        $('#detailScreen #comments').show();

                        // make sure the current user has his own comments list
                        $.post('/postif'+app.getUserCommentsPath(id), {value: '{}'});

                        // get all the comments lists under the current photo id
                        $.ajax({
                            type: 'GET',
                            url: '/getall'+app.getCommentsPath(id),
                            success: function(data) {
                                app.detail.comments.commentsList = app.detail.comments._processCommentsData(eval('(' + data + ')'));

                                app.detail.comments.render();
                                app.loading.hide();
                            },
                            error: function (xhr, textStatus, errorThrown) {
                                if (xhr.status == 404) {
                                    app.error.set('404');
                                }
                                else {
                                    app.error.set('A fatal error has occurred. Please try again later.');
                                }
                            }
                        });
                    }
                    else {
                        $('#detailScreen #comments').hide();
                    }
                },
                _processCommentsData: function(data) {
                    var ret = [];
                    for (var d in data) {
                        for (var c in data[d]) {    
                            ret.push(data[d][c]);
                        }
                    }

                    // sort by date
                    ret = ret.sort(function(a, b) {
                        return (a.updated < b.updated);
                    });

                    return ret;
                },
                addComment: function(id, comment) {
                    if (!app.detail.comments.commentsList) {
                        return;
                    }
                    app.detail.comments.commentsList.unshift(comment);
                    return;
                },
                onsubmit: function() {
                    /* validate the form */
                    if (app.util.isEmpty($('#commentForm #comment').val())) {
                        alert('Please enter a comment');
                        return false;
                    }
                    return true;
                },
                save: function() {
                    if (!app.detail.comments.onsubmit()) {
                        return false;
                    }
                    app.loading.show();
                    var comment = {
                        id: app.util.generateUID(peerscape.contentInfo.viewer.iid),
                        value: peerscape.common.escapeHTML($('#commentForm #comment').val()),
                        created: app.util.getTimestamp(),
                        updated: app.util.getTimestamp(),
                        owner: {
                            iid: peerscape.contentInfo.viewer.iid,
                            name: peerscape.contentInfo.viewer.name
                        }
                    }
                    var photoId = app.detail.getCurId();
                    $.post('/post'+app.getUserCommentsPath(photoId), {
                        value: $.toJSON(comment),
                        insertpath: '$set.'+comment.id
                    });

                    app.detail.comments.addComment(photoId, comment);
                    app.detail.comments.render();
                    $('#commentForm #comment').val('');
                    app.loading.hide();
                    return true;
                },
                render: function() {
                    if (!app.metadata) {
                        return;
                    }
                    app.detail.comments.removeAll();

                    var comments = app.detail.comments.commentsList;
                    if (comments && comments.length > 0) {
                        for (var c in comments) {
                            var item = app.detail.COMMENT_TEMPLATE.clone();
                            app.detail.comments._renderItem(item, comments[c]);
                            $('#comments ul').append(item);
                        }
                        peerscape.common.resize();
                    }
                    else {
                        $('#comments ul').html('<li>No comments</li>');
                    }
                },
                _renderItem: function(item, comment, i) {
                    //item.attr('id', comment.id);
                    item.find('h4 a').eq(0)
                        .attr('href', 'http://' + comment.owner.iid + '.hexlabel.net/')
                        .attr('target', '_top')
                        .html(comment.owner.name);

                    item.find('p.updated').eq(0)
                        .html(app.util.formatTimestamp(comment.updated));

                    item.find('p.commentBody').eq(0)
                        .html(comment.value);

                    if (app.util.isAdmin(peerscape.contentInfo)) {
                        item.find('.commentNav a.delete')
                            .bind('click', function() {
                                if (confirm('Are you sure you want to delete this comment?')) {
                                    app.detail.comments.deleteComment(comment.owner.iid, comment.id);
                                }
                                return false;
                            })
                            .show();
                    }
                    else {
                        item.find('.commentNav a.delete').hide();
                    }
                },
                deleteComment: function(iid, commentId) {
                    if (!app.metadata || !app.detail.curItem) {
                        return false;
                    }

                    $.post('/delete'+app.getUserCommentsPath(app.detail.getCurId(), iid), {
                        insertpath: '$set.'+commentId
                    });

                    for (var c in app.detail.comments.commentsList) {
                        if (app.detail.comments.commentsList[c].id == commentId) {
                            delete app.detail.comments.commentsList[c];
                            break;
                        }
                    }

                    app.detail.comments.removeAll();
                    app.detail.comments.render();
                },
                removeAll: function() {
                    $('#comments ul').empty();
                },
            }
        },
        /* -------------- SETTINGS ---------------- */
        settings: {
            init: function() {
                $('#settingsForm').submit(function() { return false; });
                $('#settingsForm input.submit')
                    .bind('click', function() {
                        app.settings.save();
                        app.util.log('load 12');
                        app.load('home');
                        return false;
                    });

                // register this screen
                app.screens['settingsScreen'] = $('#settingsScreen');
            },
            onsubmit: function() {
                if (app.util.isEmpty($('#settingsForm #albumTitle').val())) {
                    alert('Please enter a title');
                    return false;
                }
                return true;
            },
            save: function() {
                if (!app.settings.onsubmit()) {
                    return false;
                }
                app.loading.show();

                // set the title
                $.post('/content/title', {
                    value: peerscape.common.escapeHTML($('#settingsForm #albumTitle').val())
                });
                peerscape.contentInfo.title = peerscape.common.escapeHTML($('#settingsForm #albumTitle').val());
                app.home.setTitle(peerscape.common.escapeHTML($('#settingsForm #albumTitle').val()));

                // set the various prefs
                /*
                $('#settingsForm #autoRefresh').each(function() {
                    app.prefs.auto_refresh = this.checked;
                });
                */
                $('#settingsForm #enableComments').each(function() {
                    app.prefs.enable_comments = this.checked;
                });
                if (app.util.isGroup(peerscape.contentInfo)) {
                    if ($('#settingsForm #enableEditor').attr('checked')) {
                        app.prefs.group_write_roles = ['admin', 'editor'];
                    }
                    else {
                        app.prefs.group_write_roles = ['admin'];
                    }
                    $.post('/revoke/index', { who: peerscape.contentInfo.parent_profile.iid, pattern: '/content/photos/...'});
                    $.post('/grant/index', { who: peerscape.contentInfo.parent_profile.iid, pattern: '/content/photos/...', roles: $.toJSON(app.prefs.group_write_roles)});
                }
                $.post('/post'+app.PREFS_PATH, {value: $.toJSON(app.prefs)});

                app.loading.hide();
            },
            render: function() {
                $('#settingsForm #albumTitle').val(peerscape.common.unescapeHTML(peerscape.contentInfo.title));
                /*
                $('#settingsForm #autoRefresh').each(function() {
                    this.checked = app.prefs.auto_refresh;
                });
                */
                $('#settingsForm #enableComments').each(function() {
                    this.checked = app.prefs.enable_comments;
                });
                $('#settingsForm #enableEditor').each(function() {
                    for (var r in app.prefs.group_write_roles) {
                        if (app.prefs.group_write_roles[r] == 'editor') {
                            this.checked = true;
                            return;
                        }
                    }
                    this.checked = false;
                });

                if (app.util.isGroup(peerscape.contentInfo)) {
                    // show group-related settings
                    $('#settingsForm .group').show();
                }
                else {
                    // hide group-related settings
                    $('#settingsForm .group').hide();
                }
            },
            hide: function() {
                $('#settingsScreen').hide();
            },
            show: function() {
                app.hideAll();
                app.loading.hide();
                app.settings.render();
                $('#settingsScreen').show();
                app.util.selectTabNav('settingsTab');
                peerscape.common.resize();
            }
        },
        /* -------------- UPLOAD ---------------- */
        upload: {
            init: function() {
                $('#uploadTarget').load(function() { app.upload.onload(); });
                $('#uploadForm').attr('action', '/post/content/photos/$uuid.$ext');
                $('#uploadForm').submit(function() { return app.upload.onsubmit(); });

                // register this screen
                app.screens['uploadScreen'] = $('#uploadScreen');
            },
            onsubmit: function() {
                /* validate the form */
                if (app.util.isEmpty($('#uploadForm #value').val())) {
                    alert('Please choose a photo');
                    return false;
                }
                else if (!app.util.isImage($('#uploadForm #value').val())) {
                    alert('Please choose a valid photo');
                    return false;
                }
                else if (app.util.isEmpty($('#uploadForm #title').val())) {
                    alert('Please enter a title');
                    return false;
                }
                app.loading.show();
                return true;
            },
            onload: function() {
                var result = $('#uploadTarget').contents().text();
                if (result != 'null' && result.indexOf('/') != -1) {
                    result = eval(result);
                    var uuid = result.substr(result.lastIndexOf('/')+1);
                    if (uuid.indexOf('.') != -1) {
                        uuid = uuid.substr(0, result.lastIndexOf('.'));
                    }

                    // trigger metadata upload
                    var entry = {
                        author: {
                            iid: peerscape.contentInfo.viewer.iid,
                            name: peerscape.contentInfo.viewer.name
                        },
                        title: peerscape.common.escapeHTML($('#uploadForm #title').val()),
                        id: uuid,
                        created: app.util.getTimestamp(),
                        updated: app.util.getTimestamp(),
                        summary: peerscape.common.escapeHTML($('#uploadForm #description').val()),
                        content: {
                            src: '/get' + result
                        }
                    };

                    // add an entry for this photo
                    $.ajax({
                        type: 'POST',
                        url: '/post'+app.getSinglePhotoEntryPath(uuid),
                        data: { value: $.toJSON(entry) },
                        async: false
                    });

                    // add to local entries list
                    app.entries.unshift(entry);

                    // update the metadata
                    if (app.metadata) {
                        app.metadata.updated = app.util.getTimestamp();
                        $.post('/post'+app.METADATA_PATH, {value: $.toJSON(app.metadata)});
                    }

                    // add a comments structure for this user
                    $.post('/postif'+app.getUserCommentsPath(uuid), {value: '{}'});
                    // update the feeds
                    $.post('/post'+app.JSON_FEED_PATH, {value: $.toJSON(app.util.generateJSONFeed())});

                    // refresh thumbnails
                    app.loading.hide();
                    app.home.refresh();
                    app.util.log('load 13');
                    app.load('home');
                }
                else if (result && result.indexOf('403') != -1) {
                    app.error.set('You do not have permission to do this.');
                }
                else if (result != 'null') {
                    app.error.set('A fatal error has occurred. Please try again later.');
                }
                return false;
            },
            hide: function() {
                $('#uploadScreen').hide();
                //peerscape.common.resize();
            },
            show: function() {
                app.hideAll();
                app.loading.hide();
                $('#uploadForm #value').val('');
                $('#uploadForm #title').val('');
                $('#uploadForm #description').val('');
                $('#uploadScreen').show();
                app.util.selectTabNav('uploadTab');
                peerscape.common.resize();
            }
        },
        /* -------------- LOADING ---------------- */
        loading: {
            init: function() {
                //app.screens['loading'] = $('#loading');
                app.loading.hide();
            },
            hide: function() {
                $('#loading').hide();
            },
            show: function() {
                $('#loading').show();
                peerscape.common.resize();
            }
        },
        /* -------------- UTIL ---------------- */
        util: {
            WS_RE: /^\s*$/,
            IMAGE_RE: /(\.jpg|\.jpeg|\.png|\.gif)$/i,
            log: function(s) {
                if (!app._debug) {
                    return;
                }
                try {
                    if (console != undefined) {
                        console.log(s);
                    }
                }
                catch(e) { /* nothing */ }
            },
            isEmpty: function(s) {
                return (!s || s.match(app.util.WS_RE));
            },
            isImage: function(s) {
                return (s && s.match(app.util.IMAGE_RE));
            },
            getTimestamp: function() {
                var now = new Date();
                yyyy = now.getUTCFullYear();
                mm = now.getUTCMonth();
                ++mm;
                if (mm <= 9) {
                    mm = '0' + mm;
                }
                dd = now.getUTCDate();
                if (dd <= 9) {
                    dd = '0' + dd;
                }
                hh = now.getUTCHours();
                if (hh <= 9) {
                    hh = '0' + hh;
                }
                mi = now.getUTCMinutes();
                if (mi <= 9) {
                    mi = '0' + mi;
                }
                ss = now.getUTCSeconds();
                if (ss <= 9) {
                    ss = '0' + ss;
                }
                return now.getUTCFullYear()+'-'+mm+'-'+dd+'T'+hh+':'+mi+':'+ss+'Z';
            },
            TS_RE: /(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)/,
            formatTimestamp: function(t, brk) {
                // 2009-11-26T14:3:35Z
                var months = ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
                var parts = t.match(app.util.TS_RE);

                // this will create a date with local time offset
                var d = new Date(Date.UTC(parts[1], parseInt(parts[2])-1, parts[3], parts[4], parts[5], parts[6], 00))

                // get the 'pretty' representation
                var pretty = (brk ? ' <br/>' : ' ');
                prettyTmp = prettyDate(d.getFullYear()+'-'+(parseInt(d.getMonth()) + 1)+'-'+d.getDate()+'T'+d.getHours()+':'+d.getMinutes()+':00');
                if (prettyTmp != undefined) {
                    pretty += '(' + prettyTmp + ')';
                }
                else {
                    pretty = '';
                }

                // return in local format
                return d.toLocaleString() + pretty;
            },
            selectTabNav: function(id) {
                $('#tabNav li').each(function() { $(this).removeAttr('class'); });
                $('#tabNav li#'+id).attr('class', 'selected');
            },
            imageLoader: function(id, src, target) {
                if (app.entriesCache && app.entriesCache[id]) {
                    //cache hit
                    target.attr('src', src).removeAttr('class');
                    peerscape.common.resize();
                }
                else {
                    var img = new Image();
                    img.src = src;
                    img.onload = function() {
                        target.attr('src', src).removeAttr('class');
                        peerscape.common.resize();
                    }
                    // damned opera
                    if ($.browser.opera) {
                        target.attr('src', src);
                        target.removeAttr('class');
                        peerscape.common.resize();
                    }
                }
            },
            _uidpart: function () {
                return(((1+Math.random())*0x10000)|0).toString(16).substring(1);
            },
            generateUID: function(iid) {
                var p = iid.substr(0,8)+'-'+iid.substr(8,4)+'-'+iid.substr(12,4)+'-'+iid.substr(16,4)+'-';
		        return (p+app.util._uidpart()+app.util._uidpart()+app.util._uidpart());
            },
            _get_peerscape: function() {
                try {
                    peerscape = parent.peerscape; 
                }
                catch (e) {
                    peerscape = null;
                }
                if (!peerscape) {
                    peerscape = {
                        contentInfo: {
                            parent_profile: {},
                            owner: {},
                            viewer: {},
                            application: {}
                        },
                        common: {
                            resize: function() {}
                        }
                    }
                }
            },
            generateJSONFeed: function(metadata) {
                if (!metadata) {
                    metadata = app.metadata;
                }
                var feed = {
                    title: metadata.title,
                    link: {
                        rel: 'self',
                        href: 'http://' + metadata.id + '.hexlabel.net/get/content/feed.json'
                    },
                    id: metadata.id,
                    updated: metadata.updated,
                    generator: {
                        uri: metadata.generator.uri,
                        name: metadata.generator.name
                    },
                    entries: []
                }
                for (var e in app.entries) {
                    var entry = {
                        title: app.entries[e].title,
                        id: app.entries[e].id,
                        published: app.entries[e].created,
                        updated: app.entries[e].updated,
                        summary: app.entries[e].summary,
                        content: {
                            type: 'html',
                            value: '&lt;p class="inline"&gt;&lt;img src=&quot;http://' + metadata.id + '.hexlabel.net' + app.entries[e].content.src + '&quot; width=&quot;32&quot; height=&quot;32&quot; alt=&quot;&quot;/%gt;&lt;/p&gt;'
                        },
                        author: {
                            name: app.entries[e].author.name,
                            uri: 'http://'+app.entries[e].author.iid+'.hexlabel.net/'
                        },
                        link: {
                            rel: 'enclosure',
                            type: app.util.getImageType(app.entries[e].content.src),
                            href: 'http://' + metadata.id + '.hexlabel.net' + app.entries[e].content.src
                        }
                    };
                    feed.entries.push(entry);
                }
                return feed;
            },
            /*
            generateXMLFeed: function() {
                return '<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom"></feed>';
            },
            */
            getImageType: function(src) {
                var ext = src.substr(src.lastIndexOf('.')+1);
                if (ext == 'jpg') {
                    ext = 'jpeg';
                }
                return 'image/'+ext;
            },
            isGroup: function(info) {
                return (info.parent_profile.type == 'group');
            },
            isAdmin: function(info) {
                // view is owner
                if (info.owner.iid == info.viewer.iid) {
                    return true;
                }

                // viewer is group admin
                if (info.parent_profile.type == 'group' && info.viewer.is_group_member) {
                    for (var r in info.viewer.group_roles) {
                        if (info.viewer.group_roles[r] == 'admin') {
                            return true;
                        }
                    }
                }

                // not an admin
                return false;
            }
        }
    }
}();
$(function() {
    app.init();
    app.postInit();
});
